int pdb_initialized = 0;
static int pdb_serhnd = -1;
-#define RX_SIZE 32
-#define RX_MASK(_i) ((_i)&(RX_SIZE-1))
-static unsigned int rx_cons = 0, rx_prod = 0;
-static unsigned char rx_ring[RX_RING_SIZE];
-
static inline void pdb_put_char(unsigned char c)
{
serial_putc(pdb_serhnd, c);
static inline unsigned char pdb_get_char(void)
{
- while ( rx_cons == rx_prod )
- barrier();
- return rx_ring[RX_MASK(rx_cons++)];
-}
-
-static void pdb_rx_char(unsigned char c, struct pt_regs *regs)
-{
- if ( (rx_prod - rx_cons) != RX_SIZE )
- rx_ring[RX_MASK(rx_prod++)] = c;
+ return serial_getc(pdb_serhnd);
}
static volatile int mem_err = 0;
return;
}
- serial_set_rx_handler(pdb_serhnd, pdb_rx_char);
-
printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb);
/* Acknowledge any spurious GDB packets. */
trap_info_t *ti;
unsigned long fixup;
- __sti();
-
if (!(regs->xcs & 3))
goto fault_in_hypervisor;
struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
trap_info_t *ti;
- __sti();
-
if ( (regs->xcs & 3) != 3 )
{
if ( pdb_handle_exception(3, regs) == 0 )
__asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
- __sti();
-
if ( unlikely(addr >= LDT_VIRT_START) &&
(addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
{
trap_info_t *ti;
unsigned long fixup;
- __sti();
-
/* Badness if error in ring 0, or result of an interrupt. */
if ( !(regs->xcs & 3) || (error_code & 1) )
goto gp_in_kernel;
/* Prevent recursion. */
clts();
- __sti();
-
if ( !test_bit(PF_USEDFPU, ¤t->flags) )
{
if ( test_bit(PF_DONEFPUINIT, ¤t->flags) )
struct task_struct *tsk = current;
struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
- __sti();
-
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
/* Mask out spurious debug traps due to lazy DR7 setting */
return;
}
- __sti();
-
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
if ( (condition & (1 << 14)) != (1 << 14) )
printk("\nwarning: debug trap w/o BS bit [0x%x]\n\n", condition);
#define PARITY_MARK (5<<3)
#define PARITY_SPACE (7<<3)
+#define RXBUFSZ 32
+#define MASK_RXBUF_IDX(_i) ((_i)&(RXBUFSZ-1))
typedef struct {
- int baud, data_bits, parity, stop_bits, io_base, irq;
- serial_rx_fn rx_lo, rx_hi, rx;
- spinlock_t lock;
+ int baud, data_bits, parity, stop_bits, io_base, irq;
+ serial_rx_fn rx_lo, rx_hi, rx;
+ spinlock_t lock;
+ unsigned char rxbuf[RXBUFSZ];
+ unsigned int rxbufp, rxbufc;
} uart_t;
static uart_t com[2] = {
/*
* No need for the uart spinlock here. Only the uart's own interrupt
* handler will read from the RBR and the handler isn't reentrant.
+ * Calls to serial_getc() will disable this handler before proceeding.
*/
while ( inb(uart->io_base + LSR) & LSR_DR )
{
uart->rx_hi(c&0x7f, regs);
else if ( !(c & 0x80) && (uart->rx_lo != NULL) )
uart->rx_lo(c&0x7f, regs);
+ else if ( (uart->rxbufp - uart->rxbufc) != RXBUFSZ )
+ uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufp++)] = c;
}
}
spin_unlock_irqrestore(&uart->lock, flags);
}
+
+/* Returns TRUE if given character (*pc) matches the serial handle. */
+static int byte_matches(int handle, unsigned char *pc)
+{
+ if ( !(handle & SERHND_HI) )
+ {
+ if ( !(handle & SERHND_LO) || !(*pc & 0x80) )
+ return 1;
+ }
+ else if ( *pc & 0x80 )
+ {
+ *pc &= 0x7f;
+ return 1;
+ }
+ return 0;
+}
+
+unsigned char serial_getc(int handle)
+{
+ uart_t *uart = &com[handle & SERHND_IDX];
+ unsigned char c;
+ unsigned long flags;
+
+ spin_lock_irqsave(&uart->lock, flags);
+
+ while ( uart->rxbufp != uart->rxbufc )
+ {
+ c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
+ if ( byte_matches(handle, &c) )
+ goto out;
+ }
+
+ disable_irq(uart->irq);
+
+ /* disable_irq() may have raced execution of uart_rx(). */
+ while ( uart->rxbufp != uart->rxbufc )
+ {
+ c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)];
+ if ( byte_matches(handle, &c) )
+ goto enable_and_out;
+ }
+
+ /* We now wait for the UART to receive a suitable character. */
+ do {
+ while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
+ barrier();
+ c = inb(uart->io_base + RBR);
+ }
+ while ( !byte_matches(handle, &c) );
+
+ enable_and_out:
+ enable_irq(uart->irq);
+ out:
+ spin_unlock_irqrestore(&uart->lock, flags);
+ return c;
+}